import type { MaybeRef } from 'vue'
import type { JSX } from 'vue/jsx-runtime'

export interface MultiColsEditableTableExpose {
  getRowElementByRowKey: (value: string) => Element | null
  validated: (options?: {
    isShowTour: boolean
    delay: number
  }) => Promise<boolean>
}

export enum ETableComponentNameEnum {
  RADIO = 'Radio',
  RADIO_GROUP = 'RadioGroup',
  RADIO_BUTTON = 'RadioButton',
  CHECKBOX = 'Checkbox',
  CHECKBOX_GROUP = 'CheckboxGroup',
  CHECKBOX_BUTTON = 'CheckboxButton',
  INPUT = 'Input',
  AUTOCOMPLETE = 'Autocomplete',
  INPUT_NUMBER = 'InputNumber',
  SELECT = 'Select',
  CASCADER = 'Cascader',
  SWITCH = 'Switch',
  SLIDER = 'Slider',
  TIME_PICKER = 'TimePicker',
  DATE_PICKER = 'DatePicker',
  RATE = 'Rate',
  COLOR_PICKER = 'ColorPicker',
  TRANSFER = 'Transfer',
  DIVIDER = 'Divider',
  TIME_SELECT = 'TimeSelect',
  SELECT_V2 = 'SelectV2',
  TREE_SELECT = 'TreeSelect',
  UPLOAD = 'Upload',
  EDITOR = 'Editor',
  JSON_PRETTY = 'JsonPretty',
  JSON_EDITOR = 'JsonEditor',
  CODE_MIRROR = 'CodeMirror',
  CRON_INPUT = 'CronInput',
}

type CamelCaseComponentName =
  keyof typeof ETableComponentNameEnum extends infer K
    ? K extends string
      ? K extends `${infer A}_${infer B}`
        ? `${Capitalize<Lowercase<A>>}${Capitalize<Lowercase<B>>}`
        : Capitalize<Lowercase<K>>
      : never
    : never

export type ETableComponentName = CamelCaseComponentName

export interface ETableColumn {
  field: string
  label: string
  component?: ETableComponentName
  componentProps?: Recordable
  rules?: any[]
  class?: string
  slots?: {
    edit?: (...args: any[]) => JSX.Element | string | null
    detail?: (...args: any[]) => JSX.Element | string | null
  }
  defaultValue?: any
  // ↓ type from: TableColumn
  type?: string
  hidden?: boolean
  index?: number | ((index: number) => number)
  columnKey?: string
  width?: string | number
  minWidth?: MaybeRef<string | number>
  fixed?: boolean | 'left' | 'right'
  renderHeader?: (...args: any[]) => JSX.Element | string | null
  sortMethod?: (...args: any[]) => number
  sortBy?: string | string[] | ((...args: any[]) => string | string[])
  sortOrders?: (string | null)[]
  resizable?: boolean
  formatter?: (...args: any[]) => any
  showOverflowTooltip?: boolean
  align?: 'left' | 'center' | 'right'
  headerAlign?: 'left' | 'center' | 'right'
  className?: string
  labelClassName?: string
  selectable?: (...args: any[]) => boolean
  reserveSelection?: boolean
  filters?: Array<{ text: string, value: string }>
  filterPlacement?: string
  filterMultiple?: boolean
  filterMethod?: (...args: any[]) => boolean
  filteredValue?: string[]
  [key: string]: any
}

export interface ETableProps {
  validateRequired?: boolean
  hiddenSelection?: boolean
  hiddenIndex?: boolean
  hiddenAction?: boolean
  hiddenAdd?: boolean
  hiddenDelete?: boolean
  rowKey?: string
  columns?: Array<ETableColumn>
}

export type ETableRowData<T = Recordable> = {
  internal_id?: string
  internal_disabled?: boolean
  internal_hiddenAction?: boolean
  internal_disableSelection?: boolean
  internal_hiddenDelete?: boolean
} & T
